﻿using System.Collections.Generic;
using Game500.Client.Src;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Game500.Client
{
  class Explosion
  {
    public Explosion(AnimatedTexture texture, SoundEffectInstance sound)
    {
      Texture = texture;
      Sound = sound;
    }

    public AnimatedTexture Texture;
    public SoundEffectInstance Sound;
  }

  public class FxManager
  {
    private readonly ContentManager myContentManager;
    private const float FadeLength = 1;
    private const float MaxPitch = 1.0f;
    private const float MinPitch = -1.0f;
    private readonly SoundEffectInstance myEngineSoundInstance;
    private readonly SoundEffectInstance myFireSoundInstance;
    private readonly SoundEffectInstance myIdleEngineSoundInstance;
    private readonly List<Explosion> myExplosions = new List<Explosion>();
    private readonly Texture2D myExplosionTexture;
    private SoundEffect myExplosionSound;
    private bool myMuteEngine = false;


    public FxManager(ContentManager contentManager)
    {
      myContentManager = contentManager;
      myIdleEngineSoundInstance = contentManager.Load<SoundEffect>("allison_1500").CreateInstance();
      myEngineSoundInstance = contentManager.Load<SoundEffect>("allison_2700").CreateInstance();
      myFireSoundInstance = contentManager.Load<SoundEffect>("air_can_02i").CreateInstance();
      myExplosionSound = contentManager.Load<SoundEffect>("bomb-02");

      myExplosionTexture = contentManager.Load<Texture2D>("ExplosionA");

      myIdleEngineSoundInstance.IsLooped = true;

      myEngineSoundInstance.IsLooped = true;
    }

    public bool Boost { get; set; }

    public bool MuteEngine
    {
      set 
      {
        if (value)
        {
          myIdleEngineSoundInstance.Pause();
          myEngineSoundInstance.Pause();
        }
        else
        {
          myIdleEngineSoundInstance.Play();
          myEngineSoundInstance.Play();
        }
        myMuteEngine = value;
      }
    }

    public void Update(GameTime gameTime)
    {
      var time = (float)gameTime.ElapsedGameTime.TotalSeconds;
      if (!myMuteEngine)
      {
        if (Boost)
        {
          FadeDown(myIdleEngineSoundInstance, time, 0.0f, MaxPitch);
          FadeUp(myEngineSoundInstance, time, MinPitch, 0.0f);
        }
        else
        {
          FadeDown(myEngineSoundInstance, time, MinPitch, 0.0f);
          FadeUp(myIdleEngineSoundInstance, time, 0.0f, MaxPitch);
        }  
      }
      
      foreach (var explosion in myExplosions)
      {
        explosion.Texture.UpdateFrame(time);
      }

      myExplosions.RemoveAll(e => e.Texture.IsPaused);
    }

    private void FadeUp(SoundEffectInstance sound, float time, float minPitch, float maxPitch)
    {
      if (sound.State != SoundState.Playing) sound.Play();
      sound.Volume = MathHelper.Clamp(sound.Volume + Delta(time), 0.0f, 1.0f);
      if (minPitch == 0.0f) sound.Pitch = MathHelper.Clamp(sound.Pitch - Delta(time), minPitch, maxPitch);
      else sound.Pitch = MathHelper.Clamp(sound.Pitch + Delta(time), minPitch, maxPitch);
    }

    private void FadeDown(SoundEffectInstance sound, float time, float minPitch, float maxPitch)
    {
      sound.Volume = MathHelper.Clamp(sound.Volume - Delta(time), 0.0f, 1.0f);
      if (minPitch == 0.0f) sound.Pitch = MathHelper.Clamp(sound.Pitch + Delta(time), minPitch, maxPitch);
      else sound.Pitch = MathHelper.Clamp(sound.Pitch - Delta(time), minPitch, maxPitch);
    }

    private static float Delta(float time)
    {
      return 1.0f / (FadeLength / time);
    }

    public void Fire()
    {
      myFireSoundInstance.Play();
    }

    public void Draw(Renderer renderer)
    {
      foreach (var explostion in myExplosions)
      {
        explostion.Texture.Render(renderer);
      }
    }

    public void CreateExplosion(Renderable obj)
    {
      var explosion = new Explosion(new AnimatedTexture(obj.Position, 0.0f), myExplosionSound.CreateInstance());
      myExplosions.Add(explosion);
      explosion.Texture.Load(myExplosionTexture, 16, 12);
      explosion.Texture.Play();
      explosion.Sound.Play();
    }
  }
}